From b7c453de65310924a81a9fb902727a7d8f39c36b Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Tue, 23 Jun 2020 15:14:05 +0100
Subject: [PATCH] media: bcm2835-unicam: Fixup review comments from
 Hans.

Updates the driver based on the upstream review comments from
Hans Verkuil at https://patchwork.linuxtv.org/patch/63531/

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
 .../media/platform/bcm2835/bcm2835-unicam.c   | 70 ++++++++-----------
 1 file changed, 31 insertions(+), 39 deletions(-)

--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * BCM2835 Unicam Capture Driver
+ * BCM283x / BCM271x Unicam Capture Driver
  *
  * Copyright (C) 2017-2020 - Raspberry Pi (Trading) Ltd.
  *
@@ -573,9 +573,8 @@ static const struct unicam_fmt *find_for
 	return NULL;
 }
 
-static inline unsigned int bytes_per_line(u32 width,
-					  const struct unicam_fmt *fmt,
-					  u32 v4l2_fourcc)
+static unsigned int bytes_per_line(u32 width, const struct unicam_fmt *fmt,
+				   u32 v4l2_fourcc)
 {
 	if (v4l2_fourcc == fmt->repacked_fourcc)
 		/* Repacking always goes to 16bpp */
@@ -720,7 +719,7 @@ static void unicam_wr_dma_addr(struct un
 	}
 }
 
-static inline unsigned int unicam_get_lines_done(struct unicam_device *dev)
+static unsigned int unicam_get_lines_done(struct unicam_device *dev)
 {
 	dma_addr_t start_addr, cur_addr;
 	unsigned int stride = dev->node[IMAGE_PAD].v_fmt.fmt.pix.bytesperline;
@@ -734,7 +733,7 @@ static inline unsigned int unicam_get_li
 	return (unsigned int)(cur_addr - start_addr) / stride;
 }
 
-static inline void unicam_schedule_next_buffer(struct unicam_node *node)
+static void unicam_schedule_next_buffer(struct unicam_node *node)
 {
 	struct unicam_device *dev = node->dev;
 	struct unicam_buffer *buf;
@@ -753,7 +752,7 @@ static inline void unicam_schedule_next_
 	unicam_wr_dma_addr(dev, addr, size, node->pad_id);
 }
 
-static inline void unicam_schedule_dummy_buffer(struct unicam_node *node)
+static void unicam_schedule_dummy_buffer(struct unicam_node *node)
 {
 	struct unicam_device *dev = node->dev;
 
@@ -765,8 +764,8 @@ static inline void unicam_schedule_dummy
 	node->next_frm = NULL;
 }
 
-static inline void unicam_process_buffer_complete(struct unicam_node *node,
-						  unsigned int sequence)
+static void unicam_process_buffer_complete(struct unicam_node *node,
+					   unsigned int sequence)
 {
 	node->cur_frm->vb.field = node->m_fmt.field;
 	node->cur_frm->vb.sequence = sequence;
@@ -774,16 +773,6 @@ static inline void unicam_process_buffer
 	vb2_buffer_done(&node->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
 }
 
-static bool unicam_all_nodes_streaming(struct unicam_device *dev)
-{
-	bool ret;
-
-	ret = dev->node[IMAGE_PAD].open && dev->node[IMAGE_PAD].streaming;
-	ret &= !dev->node[METADATA_PAD].open ||
-	       dev->node[METADATA_PAD].streaming;
-	return ret;
-}
-
 static void unicam_queue_event_sof(struct unicam_device *unicam)
 {
 	struct v4l2_event event = {
@@ -906,8 +895,8 @@ static int unicam_querycap(struct file *
 	struct unicam_node *node = video_drvdata(file);
 	struct unicam_device *dev = node->dev;
 
-	strlcpy(cap->driver, UNICAM_MODULE_NAME, sizeof(cap->driver));
-	strlcpy(cap->card, UNICAM_MODULE_NAME, sizeof(cap->card));
+	strscpy(cap->driver, UNICAM_MODULE_NAME, sizeof(cap->driver));
+	strscpy(cap->card, UNICAM_MODULE_NAME, sizeof(cap->card));
 
 	snprintf(cap->bus_info, sizeof(cap->bus_info),
 		 "platform:%s", dev_name(&dev->pdev->dev));
@@ -1000,8 +989,8 @@ static int unicam_g_fmt_vid_cap(struct f
 	return 0;
 }
 
-static
-const struct unicam_fmt *get_first_supported_format(struct unicam_device *dev)
+static const struct unicam_fmt *
+get_first_supported_format(struct unicam_device *dev)
 {
 	struct v4l2_subdev_mbus_code_enum mbus_code;
 	const struct unicam_fmt *fmt = NULL;
@@ -1591,7 +1580,8 @@ static void unicam_disable(struct unicam
 	clk_write(dev, 0);
 }
 
-static void unicam_return_buffers(struct unicam_node *node)
+static void unicam_return_buffers(struct unicam_node *node,
+				  enum vb2_buffer_state state)
 {
 	struct unicam_buffer *buf, *tmp;
 	unsigned long flags;
@@ -1599,15 +1589,15 @@ static void unicam_return_buffers(struct
 	spin_lock_irqsave(&node->dma_queue_lock, flags);
 	list_for_each_entry_safe(buf, tmp, &node->dma_queue, list) {
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, state);
 	}
 
 	if (node->cur_frm)
 		vb2_buffer_done(&node->cur_frm->vb.vb2_buf,
-				VB2_BUF_STATE_ERROR);
+				state);
 	if (node->next_frm && node->cur_frm != node->next_frm)
 		vb2_buffer_done(&node->next_frm->vb.vb2_buf,
-				VB2_BUF_STATE_ERROR);
+				state);
 
 	node->cur_frm = NULL;
 	node->next_frm = NULL;
@@ -1624,7 +1614,13 @@ static int unicam_start_streaming(struct
 	int ret;
 
 	node->streaming = true;
-	if (!unicam_all_nodes_streaming(dev)) {
+	if (!(dev->node[IMAGE_PAD].open && dev->node[IMAGE_PAD].streaming &&
+	      (!dev->node[METADATA_PAD].open ||
+	       dev->node[METADATA_PAD].streaming))) {
+		/*
+		 * Metadata pad must be enabled before image pad if it is
+		 * wanted.
+		 */
 		unicam_dbg(3, dev, "Not all nodes are streaming yet.");
 		return 0;
 	}
@@ -1728,7 +1724,7 @@ err_vpu_clock:
 err_pm_put:
 	unicam_runtime_put(dev);
 err_streaming:
-	unicam_return_buffers(node);
+	unicam_return_buffers(node, VB2_BUF_STATE_QUEUED);
 	node->streaming = false;
 
 	return ret;
@@ -1773,7 +1769,7 @@ static void unicam_stop_streaming(struct
 	}
 
 	/* Clear all queued buffers for the node */
-	unicam_return_buffers(node);
+	unicam_return_buffers(node, VB2_BUF_STATE_ERROR);
 }
 
 static int unicam_enum_input(struct file *file, void *priv,
@@ -1791,14 +1787,13 @@ static int unicam_enum_input(struct file
 		inp->std = 0;
 	} else if (v4l2_subdev_has_op(dev->sensor, video, s_std)) {
 		inp->capabilities = V4L2_IN_CAP_STD;
-		if (v4l2_subdev_call(dev->sensor, video, g_tvnorms, &inp->std)
-					< 0)
+		if (v4l2_subdev_call(dev->sensor, video, g_tvnorms, &inp->std) < 0)
 			inp->std = V4L2_STD_ALL;
 	} else {
 		inp->capabilities = 0;
 		inp->std = 0;
 	}
-	sprintf(inp->name, "Camera 0");
+	snprintf(inp->name, sizeof(inp->name), "Camera 0");
 	return 0;
 }
 
@@ -2027,6 +2022,9 @@ static int unicam_s_dv_timings(struct fi
 	ret = v4l2_subdev_call(dev->sensor, video, g_dv_timings,
 			       &current_timings);
 
+	if (ret < 0)
+		return ret;
+
 	if (v4l2_match_dv_timings(timings, &current_timings, 0, false))
 		return 0;
 
@@ -2457,12 +2455,6 @@ static int register_node(struct unicam_d
 		unicam_err(unicam, "Unable to allocate dummy buffer.\n");
 		return -ENOMEM;
 	}
-
-	if (pad_id == METADATA_PAD) {
-		v4l2_disable_ioctl(vdev, VIDIOC_DQEVENT);
-		v4l2_disable_ioctl(vdev, VIDIOC_SUBSCRIBE_EVENT);
-		v4l2_disable_ioctl(vdev, VIDIOC_UNSUBSCRIBE_EVENT);
-	}
 	if (pad_id == METADATA_PAD ||
 	    !v4l2_subdev_has_op(unicam->sensor, video, s_std)) {
 		v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_STD);
